package com.core

import com.FileInfo
import com.boge.extend.TaskThreadPool
import com.logger
import java.nio.file.Path
import kotlin.io.path.*

abstract class Generation(open val fileInfo: FileInfo) {

    abstract fun createNow()

    abstract fun loadFile()

    /**
     * 验证和修复 监控目录的文件 hash 一致
     */
    abstract fun verify()

    /**
     * 清空当前生成的映射
     */
    abstract fun clear()
    abstract fun removeFile(path: Path)

    abstract fun addNowFileOrUpdate(path: Path, url: String? = null, crc: String? = null): Boolean

    /**
     * 扫描指定目录，并返回所有不被排除条件匹配的文件路径。
     *
     * @param dir 指定要扫描的目录路径。
     * @param excludeDirs 要排除的目录名称集合，这些目录及其内容不会被包含在返回的序列中。
     * @param excludeExtensions 要排除的文件扩展名集合，具有这些扩展名的文件不会被包含在返回的序列中。
     * @return 一个序列（Sequence）包含指定目录中除排除条件外的所有文件路径。
     */
    @ExperimentalPathApi
    fun scanDirectory(dir: Path, excludeDirs: Set<String>, excludeExtensions: Set<String>): Sequence<Path> {
        // 对目录进行深度优先遍历，并过滤掉符合条件的路径（即排除的目录和文件）
        return dir.walk().filter { path ->
            // 确保路径不位于排除的目录中，且不是排除的扩展名
            !excludeDirs.contains(path.name) && (
                    !path.isDirectory() ||
                            (path.isDirectory() && !excludeDirs.contains(path.fileName.toString()))
                    ) && !excludeExtensions.any { path.pathString.endsWith(it, true) }
        }
    }

    @OptIn(ExperimentalPathApi::class)
    fun allFiles(root: Path, func: ((file: Path) -> Unit)) {
        val files = scanDirectory(root, fileInfo.excludes, fileInfo.excludes)
        val group = files.groupBy {
            it.extension
        }
        val string = StringBuilder()
        string.append("统计(${root.pathString}):  ")
        group.keys.forEach {
            string.append("$it: ${group[it]?.size ?: 0}, ")
        }
        logger.info(string.toString())

        val executors = TaskThreadPool(threadFactory = Thread.ofPlatform().name("scan-file-", 0).factory())
        files.forEach {
            executors.submit {
                func.invoke(it)
            }
        }
        executors.awaitCompletion()
        executors.shutdownAndAwaitTermination()

    }

    abstract fun hasAttByUrl(path: Path): Boolean

    /**
     * 监听到的变动文件
     */
    abstract fun watchAddOrUpdate(filePath: Path)

    /**
     * 完整的删除路径
     */
    abstract fun watchDelete(filePath: Path)


}